package com.example.excel_db.service.impl;

import com.example.excel_db.dto.ExcelImportErrorDTO;
import com.example.excel_db.dto.ExcelImportTaskDTO;
import com.example.excel_db.entity.ExcelImportError;
import com.example.excel_db.entity.ExcelImportTask;
import com.example.excel_db.entity.ExcelTemplate;
import com.example.excel_db.excel.ExcelDataHandler;
import com.example.excel_db.repository.ExcelImportErrorRepository;
import com.example.excel_db.repository.ExcelImportTaskRepository;
import com.example.excel_db.repository.ExcelTemplateRepository;
import com.example.excel_db.service.ExcelImportExportService;
import jakarta.persistence.EntityNotFoundException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * Excel导入导出服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ExcelImportExportServiceImpl implements ExcelImportExportService {

    private final ExcelTemplateRepository templateRepository;
    private final ExcelImportTaskRepository taskRepository;
    private final ExcelImportErrorRepository errorRepository;
    private final ExcelDataHandler excelDataHandler;

    @Override
    @Transactional
    public ExcelImportTaskDTO importExcel(Long templateId, MultipartFile file) {
        // 检查模板是否存在
        ExcelTemplate template = templateRepository.findById(templateId)
                .orElseThrow(() -> new EntityNotFoundException("模板不存在: " + templateId));

        // 创建导入任务
        ExcelImportTask task = new ExcelImportTask();
        task.setTemplate(template);
        task.setFileName(file.getOriginalFilename());
        task.setStatus(ExcelImportTask.TaskStatus.PENDING);
        task = taskRepository.save(task);

        // 异步处理Excel导入
        processExcelImportAsync(template, file, task);

        return convertToDTO(task);
    }

    @Async("excelTaskExecutor")
    protected void processExcelImportAsync(ExcelTemplate template, MultipartFile file, ExcelImportTask task) {
        try {
            log.info("开始异步处理Excel导入: 任务ID={}, 文件名={}", task.getId(), file.getOriginalFilename());
            excelDataHandler.readExcel(template, file, task);
            log.info("Excel导入处理完成: 任务ID={}, 状态={}", task.getId(), task.getStatus());
        } catch (Exception e) {
            log.error("Excel导入处理失败: 任务ID={}", task.getId(), e);
            task.setStatus(ExcelImportTask.TaskStatus.FAILED);
            task.setErrorMessage("处理失败: " + e.getMessage());
            taskRepository.save(task);
        }
    }

    @Override
    public byte[] exportExcel(Long templateId, List<Map<String, Object>> dataList) {
        // 检查模板是否存在
        ExcelTemplate template = templateRepository.findById(templateId)
                .orElseThrow(() -> new EntityNotFoundException("模板不存在: " + templateId));

        // 导出Excel
        return excelDataHandler.writeExcel(template, dataList);
    }

    @Override
    public ExcelImportTaskDTO getImportTaskStatus(Long taskId) {
        // 检查任务是否存在
        ExcelImportTask task = taskRepository.findById(taskId)
                .orElseThrow(() -> new EntityNotFoundException("导入任务不存在: " + taskId));

        return convertToDTO(task);
    }

    @Override
    @Transactional
    public boolean cancelImportTask(Long taskId) {
        // 检查任务是否存在
        ExcelImportTask task = taskRepository.findById(taskId)
                .orElseThrow(() -> new EntityNotFoundException("导入任务不存在: " + taskId));

        // 只能取消等待中或处理中的任务
        if (task.getStatus() == ExcelImportTask.TaskStatus.PENDING || 
            task.getStatus() == ExcelImportTask.TaskStatus.PROCESSING) {
            task.setStatus(ExcelImportTask.TaskStatus.FAILED);
            task.setErrorMessage("任务已取消");
            taskRepository.save(task);
            return true;
        }

        return false;
    }

    @Override
    @Transactional
    public ExcelImportTaskDTO retryImportTask(Long taskId) {
        // 检查任务是否存在
        ExcelImportTask oldTask = taskRepository.findById(taskId)
                .orElseThrow(() -> new EntityNotFoundException("导入任务不存在: " + taskId));

        // 创建新任务
        ExcelImportTask newTask = new ExcelImportTask();
        newTask.setTemplate(oldTask.getTemplate());
        newTask.setFileName(oldTask.getFileName() + " (重试)");
        newTask.setStatus(ExcelImportTask.TaskStatus.PENDING);
        newTask = taskRepository.save(newTask);

        // TODO: 实现重试逻辑，需要保存原始文件或从其他地方获取

        return convertToDTO(newTask);
    }

    /**
     * 将实体对象转换为DTO
     */
    private ExcelImportTaskDTO convertToDTO(ExcelImportTask task) {
        if (task == null) {
            return null;
        }

        ExcelImportTaskDTO dto = new ExcelImportTaskDTO();
        BeanUtils.copyProperties(task, dto);
        dto.setTemplateId(task.getTemplate().getId());
        dto.setTemplateName(task.getTemplate().getName());

        // 转换错误记录
        if (task.getErrors() != null && !task.getErrors().isEmpty()) {
            List<ExcelImportErrorDTO> errorDTOs = task.getErrors().stream()
                    .map(this::convertToDTO)
                    .collect(Collectors.toList());
            dto.setErrors(errorDTOs);
        }

        return dto;
    }

    /**
     * 将错误记录实体对象转换为DTO
     */
    private ExcelImportErrorDTO convertToDTO(ExcelImportError error) {
        if (error == null) {
            return null;
        }

        ExcelImportErrorDTO dto = new ExcelImportErrorDTO();
        BeanUtils.copyProperties(error, dto);
        dto.setTaskId(error.getTask().getId());
        return dto;
    }
}